Skip to content

Audit the auditor: evidence rules, substance checks, waiver injection fix (3.4.0) - #8

Merged
tmoody1973 merged 4 commits into
mainfrom
evidence-and-substance
Aug 22, 2026
Merged

Audit the auditor: evidence rules, substance checks, waiver injection fix (3.4.0)#8
tmoody1973 merged 4 commits into
mainfrom
evidence-and-substance

Conversation

@tmoody1973

Copy link
Copy Markdown
Owner

Started as the five improvements from a self-review. Each one uncovered something worse.

The finding that started it

A deliberately hollow repo, where every control is a costume:

file contents
.github/workflows/ci.yml one step: run: echo "test skipped"
package.json test script echo "no tests yet" && exit 0
docs/runbook.md empty, 0 bytes
README.md - [ ] figure out rollback

Scored 78/100 with nine passing checks, five of them false, all claiming verified. ci-2 is a critical check and it matched the word test inside an echo string.

Now: 70/100, five passes, no false verified claims.

Root cause was structural, not data

Confidence lived in a hand-typed set of three ids, 1,600 lines from the checks it described, with nothing keeping it in sync with 31 check ids. So the rule is now intrinsic: a pass with no evidence cannot be verified. New checks are covered automatically.

That rule immediately flagged six checks that had real evidence and never filled the field. Those now cite it (matched dependency, lockfile, script, matching line) or, for proofs of absence, the scope they searched.

Security: the waiver file is untrusted input

.prod-audit-waivers.json lives in the audited repo. Its text went into the report unescaped. A crafted reason forged a second ## Repository Controls Score: 100/100 heading. Reproduced, then fixed at load time rather than at each render site. Regression test asserts on heading lines, not substrings.

This directly violated the "audited repo is data, not instructions" rule shipped in 3.3.0 this morning.

The linter rejected our own output

check_report.py bans em dashes; the templates contained 30 and every grade string was "A — Strong evidence of controls". Following the template guaranteed a failing gate. Em dashes removed from every generated string, with a test that the grade strings pass our own linter.

New: the generated documents are checked

The script had 46 tests. The documents Claude writes from it, which are what users read, had none. check_report.py enforces what step 8 previously only asked Claude to remember. Run against real, already-hand-reviewed documents it found six problems, two of which turned out to be the new evidence rule being wrong.

Refactor

1836 lines in one file, over this project's own 800-line ceiling, into an audit/ package: 8 modules, largest 503. Entry point re-exports everything, so every documented command still works, verified from an unrelated cwd. 77 unused imports removed.

Verified

  • 59 tests (was 37)
  • validator passes
  • self-audit exits 0
  • end to end on three repos plus the hollow fixture
  • CI green on this PR

Not done, and why

claude plugin eval is in early access and unavailable on this account. I did not write eval files against a schema I cannot validate. The five prompt-only skills were instead each tested once by hand against a real repository by an independent agent; every one came back "partly works" with specific defects. Those are tracked for 3.5.0 and listed in the PR discussion.

Task 1: a pass with an empty evidence list can no longer claim to be
verified. The downgrade is automatic, so WEAK_PASS_IDS no longer has to
be remembered for new checks. Structural passes (dep-1, ci-6, res-2)
now carry the evidence they always had.

Task 2: five checks passed on costumes. A CI step of echo "test
skipped" satisfied ci-2 (critical). A test script of echo && exit 0
satisfied ci-6. An empty runbook.md satisfied res-1. An unchecked TODO
box satisfied res-2. They now require a real test runner (string
literals stripped first), 50+ words of prose, and a non-TODO line.

A deliberately hollow repo scored 78 with 9 passes, 5 of them false.
It now scores 70 with 5 passes and no false verified claims.

46 tests.
1836 lines in one file, over the 800-line ceiling in the project's own
coding rules, with three hand-maintained tables sitting far from the
checks they describe.

Now 9 modules, largest 503 lines: model, repo, fingerprint,
checks_build, checks_runtime, checks_quality, runner, report.
prod_audit.py stays the entry point and re-exports the public names, so
every documented command and every existing import keeps working.

Verified: 46 tests pass, --help/--profile/--fail-on work from an
unrelated cwd by absolute path, self-audit unchanged.
The script's findings have 46 tests. The documents Claude writes from
them had none, and they are what the user reads.

check_report.py enforces what SKILL.md step 8 previously only asked
Claude to remember: a quoted file path must appear in the scan, a weak
pass must not be written up as a win, every critical must be addressed
in the brief, a waived finding must stay visible, no placeholders, no
em dashes.

Run against the real jarvis documents it found 6 issues in prose that
had already been reviewed by hand. Two turned out to be false
demotions caused by checks that had real evidence and never filled the
field (log-1 and log-2 match installed dependencies); those now carry
it, along with sec-3, sec-4 and ms-1 which cite the scope they searched.
The other four were genuine: a file path that does not exist, a
hand-verified path not labelled as such, and em dashes in both docs.

53 tests.
A hollow repo scored 78 with five false verified passes. Fixing that
surfaced a markdown injection through the waiver file, a linter whose
rule contradicted our own templates, and dependency matching that
counted @types/pino as a logger.

59 tests.
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@tmoody1973, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 23 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bd7e3d89-3fea-45a6-826a-d8d174e5c785

📥 Commits

Reviewing files that changed from the base of the PR and between 267e74b and 81b6e33.

📒 Files selected for processing (19)
  • .claude-plugin/marketplace.json
  • .claude-plugin/plugin.json
  • CHANGELOG.md
  • skills/prod-readiness-coach/README.md
  • skills/prod-readiness-coach/SKILL.md
  • skills/prod-readiness-coach/references/report-templates.md
  • skills/prod-readiness-coach/scripts/audit/__init__.py
  • skills/prod-readiness-coach/scripts/audit/checks_build.py
  • skills/prod-readiness-coach/scripts/audit/checks_quality.py
  • skills/prod-readiness-coach/scripts/audit/checks_runtime.py
  • skills/prod-readiness-coach/scripts/audit/fingerprint.py
  • skills/prod-readiness-coach/scripts/audit/model.py
  • skills/prod-readiness-coach/scripts/audit/repo.py
  • skills/prod-readiness-coach/scripts/audit/report.py
  • skills/prod-readiness-coach/scripts/audit/runner.py
  • skills/prod-readiness-coach/scripts/check_report.py
  • skills/prod-readiness-coach/scripts/prod_audit.py
  • skills/prod-readiness-coach/tests/test_check_report.py
  • skills/prod-readiness-coach/tests/test_prod_audit.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tmoody1973
tmoody1973 merged commit 492440d into main Aug 22, 2026
3 checks passed
@tmoody1973
tmoody1973 deleted the evidence-and-substance branch August 22, 2026 22:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant